package shuaige.jdk.多线程.concurrent.completableFuture;

import cn.hutool.core.date.DateUtil;

import java.util.Date;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class 结果处理_异步计算后_组合上一阶段 {
    private static ExecutorService executor1 = Executors.newSingleThreadExecutor();
    private static ExecutorService executor2 = Executors.newSingleThreadExecutor();

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        thenCombine_合并();
    }

    public static void thenCompose_组合() throws ExecutionException, InterruptedException {
        // 当此阶段正常完成时，将使用此阶段的结果作为参数调用给定函数，返回另一个 CompletionStage。
        // 当该阶段正常完成时，此方法返回的 CompletionStage 以相同的值完成。
        // 为确保进度，提供的函数必须安排其结果的最终完成
        System.out.println("开始：" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        CompletableFuture<String> completableFuture
                = CompletableFuture.supplyAsync(() -> {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "Hello";
                })
                .thenCompose(s -> CompletableFuture.supplyAsync(() -> {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return s + " Hello!";
                }));
        System.out.println("get:" + completableFuture.get());
        System.out.println("结束：" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
    }

    public static void thenCombine_合并() throws ExecutionException, InterruptedException {
        System.out.println("开始：" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
        CompletableFuture<String> completableFuture
                = CompletableFuture.supplyAsync(() -> {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "Hello";
                })
                // 当这个阶段和另一个给定阶段都正常完成时，将两个结果作为提供函数的参数执行
                .thenCombine(CompletableFuture.supplyAsync(
                        () -> " World"), (s1, s2) -> {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return s1 + s2;
                });
        System.out.println("get:" + completableFuture.get());
        System.out.println("结束：" + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
    }

    public static void thenAcceptBoth_组合但不返回值() throws ExecutionException, InterruptedException {
        CompletableFuture future = CompletableFuture.supplyAsync(() -> {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return "Hello";
                })
                // 当这个阶段和另一个给定阶段都正常完成时，将两个结果作为所提供操作的参数执行
                .thenAcceptBoth(CompletableFuture.supplyAsync(() -> " World"),
                        (s1, s2) -> System.out.println(s1 + s2));
        System.out.println("future:" + future.get());
    }

}
